/***************************************************************************
 *   Salatinoid - Islamic Prayer Time Plasmoid                             *
 *   Copyright (C) 2009 by Tarek Saidi  <tarek.saidi@arcor.de>             *
 *                                                                         *
 *   Bismillah ar-Rahman ar-Rahim;                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation, either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program. If not, see <http://www.gnu.org/licenses/>.  *
 ***************************************************************************/

#include "plasma-applet-salatinoid.h"
#include "plasma-applet-salatinoidconfig.h"

K_EXPORT_PLASMA_APPLET(salatinoid, Salatinoid)
K_GLOBAL_STATIC_WITH_ARGS(KComponentData,salatinoidComponent,("plasma-applet-salatinoid",QByteArray(),KComponentData::SkipMainComponentRegistration))

const static bool test_enabled = false;
const static float  test_dayLen = 300; //Length of one simulated day in seconds

static int NAME_COLUMN      = 0;
static int TIME_COLUMN      = 1;
static int TIME_LEFT_COLUMN = 2;

Salatinoid::Salatinoid(QObject *parent, const QVariantList &args) : Plasma::Applet(parent, args) {
    setHasConfigurationInterface(true);
    prayerLabelFont = QFont("Utopia",14,true);
    limitLabelFont  = QFont("Utopia",10,false);
    prayerTimeFont  = QFont("Arial",8,false);
    timeLeftFont    = QFont("Arial",9,true);
    prayerNames[0] = i18n("Fajr");
    prayerNames[1] = i18n("Sunrise");
    prayerNames[2] = i18n("Zuhr");
    prayerNames[3] = i18n("Assr");
    prayerNames[4] = i18n("Maghrib");
    prayerNames[5] = i18n("Isha");
    prayerNames[6] = i18n("Midnight");
    beginsInText   = i18n("begins in %1 hours");
    endsInText     = i18n("ends in %1 hours");
    configDlg      = NULL;
    now            = QDateTime::currentDateTime();
    currentPrayer  = UNINIT;
    nextPrayer     = UNINIT;
}
 
Salatinoid::~Salatinoid(){
    delete icon;
    delete background;
    if(configDlg)
        delete configDlg;
}

void Salatinoid::init(){
    //Workaround for Qt Bug #233662 fixed in release 4.5
    if(QT_VERSION < 0x040500 && layoutDirection() == Qt::RightToLeft){
        NAME_COLUMN      = 2;
        TIME_COLUMN      = 1;
        TIME_LEFT_COLUMN = 0;
    }
    // \End Workaround

    icon = new KIcon("salatinoid");
    background = new QPixmap(KStandardDirs::locate("data","desktoptheme/default/widgets/plasma-applet-salatinoid-background.png"));
    setAspectRatioMode(Plasma::IgnoreAspectRatio);
    graphicsLayout = new QGraphicsGridLayout();
    graphicsLayout->setContentsMargins(20,10,20,10);
    for(int i=FAJR; i<=NISFULLAYL; i++){
        nameLabels[i] = new GraphicsTextWidget(prayerNames[i]);
        nameLabels[i]->setFont( (i==SHUROUK || i==NISFULLAYL) ? limitLabelFont : prayerLabelFont );
        nameLabels[i]->setTextAlign(Qt::AlignRight | Qt::AlignVCenter);
        nameLabels[i]->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);
        graphicsLayout->addItem(nameLabels[i],i,NAME_COLUMN);
        timeLabels[i] = new GraphicsTextWidget("00:00");
        timeLabels[i]->setFont(prayerTimeFont);
        timeLabels[i]->setTextAlign(Qt::AlignLeft | Qt::AlignVCenter);
        timeLabels[i]->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);
        graphicsLayout->addItem(timeLabels[i],i,TIME_COLUMN);
    }
    graphicsLayout->setColumnSpacing(NAME_COLUMN,15);
    graphicsLayout->setColumnSpacing(TIME_COLUMN,15);
    timeLeftLabel = new GraphicsTextWidget(beginsInText.arg("00:00"));
    timeLeftLabel->setFont(timeLeftFont);
    timeLeftLabel->setTextAlign(Qt::AlignRight | Qt::AlignVCenter);
    timeLeftLabel->setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::Fixed);
    graphicsLayout->addItem(timeLeftLabel,0,TIME_LEFT_COLUMN);
    timeLeftLabelIndex = graphicsLayout->count() - 1;
    setLayout(graphicsLayout);
    //Determine the minimum size by testing both labels "ends in..." and "begins in..."
    QSizeF minSize1 = graphicsLayout->effectiveSizeHint(Qt::MinimumSize);
    timeLeftLabel->setText(endsInText.arg("00:00"));
    QSizeF minSize2 = graphicsLayout->effectiveSizeHint(Qt::MinimumSize);
    QSizeF minSize = (minSize1.width() > minSize2.width()) ? minSize1 : minSize2;
    qreal margins[4];
    getContentsMargins(margins, margins+1, margins+2, margins+3);
    minSize += QSizeF(margins[0]+margins[2] + 10 ,margins[1]+margins[3]);
    setMinimumSize(minSize);
    setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
    applyParameters();
    test_timer.setInterval(100);
    connect(&test_timer,SIGNAL(timeout()),this,SLOT(test_incrementTime()));
    test_timer.start();
}


void Salatinoid::applyParameters(){
    Plasma::DataEngine *salatinoidEngine = dataEngine("salatinoid");
    salatinoidEngine->disconnectSource("salatinoid", this);
    salatinoidEngine = dataEngine("salatinoid");
    salatinoidEngine->setProperty("latitude", SalatinoidConfig::latitude());
    salatinoidEngine->setProperty("longitude", SalatinoidConfig::longitude());
    salatinoidEngine->setProperty("calculationMethod", SalatinoidConfig::calculationMethod());
    salatinoidEngine->setProperty("seaLevel", SalatinoidConfig::seaLevel());
    salatinoidEngine->connectSource("salatinoid", this, 500, Plasma::AlignToMinute);
}


void Salatinoid::updateConfiguration(){
    applyParameters();
    updateMessages();
}

void Salatinoid::dataUpdated(const QString& source, const Plasma::DataEngine::Data &data){
    if(!test_enabled){
        now = QDateTime::currentDateTime();
    }
    //Fetch times from the data engine
    prayerTimes[0] = data["fajr"].toDateTime();
    prayerTimes[1] = data["shurouk"].toDateTime();
    prayerTimes[2] = data["zuhr"].toDateTime();
    prayerTimes[3] = data["assr"].toDateTime();
    prayerTimes[4] = data["maghrib"].toDateTime();
    prayerTimes[5] = data["isha"].toDateTime();
    prayerTimes[6] = data["nisfullayl"].toDateTime();
    //Determine current prayer
    int lastPrayer = currentPrayer;
    currentPrayer = NONE;
    nextPrayer    = FAJR;
    for(int i=FAJR; i<=NISFULLAYL; i++){
        if(now >= prayerTimes[i]){
            currentPrayer = (PrayerTime) ((i != SHUROUK) ? i : -1);
            nextPrayer = (PrayerTime) (i+1);
        }
    }
    updateMessages();
    //Send notification if a new prayer time was entered
    if(lastPrayer != currentPrayer && lastPrayer != UNINIT && currentPrayer != NONE){
        QString msg = (layoutDirection() == Qt::RightToLeft) ? "<h1 dir=\"rtl\">%1</h1>" : "<h1 dir=\"ltr\">%1</h1>";
        msg = msg.arg(i18n("Now: %1 prayer.",prayerNames[currentPrayer]));
        KNotification::event("prayer_time", msg, icon->pixmap(32,32), 0L,
                             KNotification::CloseOnTimeout,
                             *salatinoidComponent);
    }
}


void Salatinoid::updateMessages(){
    for(int i=FAJR; i<=NISFULLAYL; i++)
        timeLabels[i]->setText(formatPrayerHour(prayerTimes[i].time()));

    graphicsLayout->removeAt(timeLeftLabelIndex);
    if(currentPrayer != -1){
        timeLeftLabel->setText(endsInText.arg(timeLeftString(prayerTimes[nextPrayer])));
        graphicsLayout->addItem(timeLeftLabel,currentPrayer,TIME_LEFT_COLUMN);
    }
    else{
        timeLeftLabel->setText(beginsInText.arg(timeLeftString(prayerTimes[nextPrayer])));
        graphicsLayout->addItem(timeLeftLabel,nextPrayer,TIME_LEFT_COLUMN);
    }
    update();
}


QString Salatinoid::timeLeftString(const QDateTime& t) const{
  int seconds = now.secsTo(t);
  int hours = seconds / (60 * 60);
  seconds -= hours * 60 *60;
  int minutes = seconds / (60);
  QString hour_string = QString::number(hours);
  QString min_string = QString::number(minutes);
  min_string.prepend((minutes<10)?"0":"");
  return hour_string + ":" + min_string;
}

QString Salatinoid::formatPrayerHour(const QTime &time) const {
  return time.toString("HH:mm");
}


void Salatinoid::paintInterface(QPainter *p, const QStyleOptionGraphicsItem *option, const QRect &contentsRect){
    Q_UNUSED(option);
    // Draw background
    p->setRenderHint(QPainter::SmoothPixmapTransform);
    p->setRenderHint(QPainter::Antialiasing);
    p->drawTiledPixmap(contentsRect, *background);
    p->setPen(Qt::white);

    // Draw Marker
    if(currentPrayer!=-1){
        p->setBrush(QBrush(QColor(255,0,0,100)));
        QRectF rect;
        rect.setLeft(contentsRect.left() + 10);
        rect.setRight(contentsRect.right() - 10.0 );
        rect.setTop(nameLabels[currentPrayer]->geometry().top());
        rect.setBottom(nameLabels[currentPrayer]->geometry().bottom());
        p->drawRoundedRect(rect,5,5,Qt::RelativeSize);
    }
    else {
        p->setBrush(QBrush(QColor(0,255,0,100)));
        QRectF rect;
        rect.setLeft(contentsRect.left() + 10);
        rect.setRight(contentsRect.right() - 10.0 );
        rect.setTop(nameLabels[nextPrayer]->geometry().top());
        rect.setBottom(nameLabels[nextPrayer]->geometry().bottom());
        p->drawRoundedRect(rect,5,5,Qt::RelativeSize);

    }
}

void Salatinoid::test_incrementTime(){
    float factor = (24.0*60.0*60.0) / test_dayLen;
    now = now.addSecs(0.1 * factor);
    if(now > prayerTimes[NISFULLAYL]){
        now = now.addDays(-1);
    }
    dataUpdated(QString(),dataEngine("salatinoid")->query("DATA"));
}


#include "plasma-applet-salatinoid.moc"
